package com.happy.xiao.common.rabbitmq.service.impl;

import com.happy.xiao.common.rabbitmq.bean.MessageReliabilityDelay;
import com.happy.xiao.common.rabbitmq.service.ICommonMessage;
import com.happy.xiao.common.rabbitmq.service.IReliabilityMessage;
import com.happy.xiao.common.utils.Util;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service("ReliabilityMessageService")
public class ReliabilityMessageImpl implements IReliabilityMessage {

    @Autowired
    private Environment env;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    ICommonMessage iCommonMessage;

    // 这里是用于消息消费确认检测的延时发送消息时间 == 确保消息真正消费了  【这个时间具体看业务逻辑】
    private final static int reliability_check_delay_time = 10 * 1000;


    /**
     * 消息消费确认机制  【可靠性信息】
     *
     * @param message 消息内容
     * @return
     * @throws Exception
     */
    @Override
    public boolean sendReliabilityConfirmMessage(String message) throws Exception {
        String exchange = env.getProperty("check.confirm.exchange.name");
        String routingKey = env.getProperty("check.confirm.routing.key.name");
        return iCommonMessage.sendNormal(rabbitTemplate, exchange, routingKey, message);
    }

    /**
     * 发送检测信息是否消费成功的延时信息
     *
     * @param object
     * @return
     * @throws Exception
     */
    @Override
    public boolean sendReliabilityCheckDelayMessage(MessageReliabilityDelay object) throws Exception {
        String message = Util.ObjectToJson(object);
        return createReliabilityCheckDelay(message, reliability_check_delay_time);
    }

    /**
     * 发送检测信息是否消费成功的延时信息
     *
     * @param object
     * @param times
     * @return
     * @throws Exception
     */
    @Override
    public boolean sendReliabilityCheckDelayMessage(MessageReliabilityDelay object, long times) throws Exception {
        String message = Util.ObjectToJson(object);
        if (times == 0) times = reliability_check_delay_time;

        return createReliabilityCheckDelay(message, times);
    }

    /**
     * 创建检测信息是否消费成功的延时信息
     *
     * @param message
     * @param times
     * @return
     * @throws Exception
     */
    private boolean createReliabilityCheckDelay(String message, long times) throws Exception {
        String exchange = env.getProperty("check.produce.exchange.name");
        String routingKey = env.getProperty("check.produce.routing.key.name");
        return iCommonMessage.sendDelay(rabbitTemplate, exchange, routingKey, message, times);
    }


    // TODO ------------------------------------------------------------------------------------------------------------
    // TODO ------------------------------------------------------------------------------------------------------------
    // TODO ------------------------------------------------------------------------------------------------------------


    /**
     * 可靠性普通消息
     *
     * @param exchange
     * @param routingKey
     * @param message
     * @param callbackUrl
     * @return
     * @throws Exception
     */
    @Override
    public boolean sendReliabilityNormalMessage(String exchange,
                                                String routingKey,
                                                String message,
                                                String callbackUrl) throws Exception {
        return sendReliabilityNormalMessage(exchange, routingKey, message, callbackUrl, reliability_check_delay_time);
    }


    /**
     * 可靠性普通消息
     *
     * @param exchange
     * @param routingKey
     * @param message
     * @param callbackUrl
     * @param reliabilityTimes       毫秒
     * @return
     * @throws Exception
     */
    @Override
    public boolean sendReliabilityNormalMessage(String exchange,
                                                String routingKey,
                                                String message,
                                                String callbackUrl,
                                                long reliabilityTimes) throws Exception {
        return createReliabilityMessage(exchange, routingKey, message, callbackUrl, 0, reliabilityTimes);
    }

    @Override
    public boolean sendReliabilityDelayMessage(String exchange,
                                               String routingKey,
                                               String message,
                                               String callbackUrl,
                                               long delayTimes) throws Exception {
        return sendReliabilityDelayMessage(exchange, routingKey, message, callbackUrl, delayTimes, reliability_check_delay_time);
    }

    @Override
    public boolean sendReliabilityDelayMessage(String exchange,
                                               String routingKey,
                                               String message,
                                               String callbackUrl,
                                               long delayTimes,
                                               long reliabilityTimes) throws Exception {
        return createReliabilityMessage(exchange, routingKey, message, callbackUrl, delayTimes, reliabilityTimes);
    }


    /**
     * @param exchange
     * @param routingKey
     * @param message
     * @param callbackUrl
     * @param delayTimes       延时消息，如果这个不为0，则这个消息是属于延时消息队列的
     * @param reliabilityTimes 可靠性队列的延时消息时间【如果发送的消息属于延时队列的消息，
     *                         这个时间会加上delayTimes， 这样的可靠性消息，会在延时消息处理之后】
     * @return
     * @throws Exception
     */
    private boolean createReliabilityMessage(String exchange,
                                             String routingKey,
                                             String message,
                                             String callbackUrl,
                                             long delayTimes,
                                             long reliabilityTimes) throws Exception {
        if (StringUtils.isEmpty(exchange)
                || StringUtils.isEmpty(routingKey)
                || StringUtils.isEmpty(message)) return false;

        if (StringUtils.isEmpty(callbackUrl)) callbackUrl = "";

        // 这里设置可靠性消息的 死亡队列时间
        if (reliabilityTimes <= 0 ) reliabilityTimes = reliability_check_delay_time;


        // 创建信息ID
        String messageID = iCommonMessage.createMessageID();

        long times = reliabilityTimes;

        if (delayTimes <= 0) {
            // 这里是发送普通的消息
            iCommonMessage.sendNormal(rabbitTemplate, exchange, routingKey, message, messageID);
        } else {

            // 这里是延时消息
            iCommonMessage.sendDelay(rabbitTemplate, exchange, routingKey, message, messageID, delayTimes);
            times += delayTimes;   // 这里确保可靠性消息在延时消息后面
        }

        MessageReliabilityDelay delayBean = new MessageReliabilityDelay(messageID, callbackUrl);
        sendReliabilityCheckDelayMessage(delayBean, times);
        return true;
    }

}
